home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (c) 1992 The Geometry Center; University of Minnesota
- 1300 South Second Street; Minneapolis, MN 55454, USA;
-
- This file is part of geomview/OOGL. geomview/OOGL is free software;
- you can redistribute it and/or modify it only under the terms given in
- the file COPYING, which you should have received along with this file.
- This and other related software may be obtained via anonymous ftp from
- geom.umn.edu; email: software@geom.umn.edu. */
-
- /* Authors: Charlie Gunn, Stuart Levy, Tamara Munzner, Mark Phillips */
-
- #include <stdio.h>
- #include <string.h>
- #include "geomclass.h"
- #include "streampool.h"
- #include "handleP.h"
-
-
- HandleOps GeomOps = {
- "geom",
- GeomStreamIn,
- GeomStreamOut,
- GeomDelete,
- NULL, /* resync */
- NULL, /* close pool */
- };
-
- Geom *
- GeomLoad(char *fname)
- {
- FILE *inf = fopen(fname, "r");
- Geom *g;
-
- if(inf == NULL) {
- OOGLError(0, "GeomLoad: can't open %s: %s", fname, sperror());
- return NULL;
- }
- g = GeomFLoad(inf, fname);
- fclose(inf);
- return g;
- }
-
- Geom *
- GeomFLoad(FILE *inf, char *fname)
- {
- Pool *p;
- Geom *g = NULL;
-
- p = PoolStreamTemp(fname, inf, 0, NULL);
- GeomStreamIn(p, NULL, &g);
- PoolDelete(p);
- return g;
- }
-
- int
- GeomFLoadEmbedded( Geom **gp, Handle **hp, FILE *inf, char *fname )
- {
- Pool *p;
- int nope;
-
- p = PoolStreamTemp(fname, inf, 0, NULL);
- nope = GeomStreamIn(p, hp, gp);
- PoolDelete(p);
- return !nope;
- }
-
- Geom *
- GeomSave(Geom *g, char *fname)
- {
- Pool *p;
- int ok;
-
- p = PoolStreamTemp(fname, NULL, 1, &GeomOps);
- if(p == NULL) {
- OOGLError(0, "GeomSave: Can't open %s: %s", fname, sperror());
- return NULL;
- }
- PoolSetOType(p, PO_DATA);
- ok = GeomStreamOut(p, NULL, g);
- PoolClose(p);
- PoolDelete(p);
- return ok ? g : NULL;
- }
-
- Geom *
- GeomFSave(Geom *g, FILE *outf, char *fname)
- {
- Pool *p;
- int ok;
-
- p = PoolStreamTemp(fname, outf, 1, NULL);
- PoolSetOType(p, PO_DATA);
- PoolIncLevel(p,1);
- ok = GeomStreamOut(p, NULL, g);
- PoolDelete(p);
- return ok ? g : NULL;
- }
-
- Geom *
- GeomFSaveEmbedded( Geom *g, Handle *handle, FILE *outf, char *fname )
- {
- Pool *p;
- int ok;
-
- p = PoolStreamTemp(fname, outf, 1, NULL);
- PoolSetOType(p, PO_HANDLES);
- PoolIncLevel(p, 1); /* Enforce level > 0 to get { braces } */
- ok = GeomStreamOut(p, handle, g);
- PoolDelete(p);
- return ok ? g : NULL;
- }
-
- int
- GeomEmbedPrefix(int c)
- { return (c == '{' || c == '=' || c == '@' || c == '<'); }
-
- int
- GeomStreamIn(Pool *p, Handle **hp, Geom **gp)
- {
- FILE *f;
- Handle *h = NULL;
- Handle *hname = NULL;
- Geom *g = NULL;
- Handle *aphandle = NULL;
- Appearance *ap = NULL;
- GeomClass *Class;
- void *it;
- struct stdio_mark *mark = NULL;
- int first;
- int empty = 1, braces = 0;
- Geom **tgp;
- Handle **thp;
- int c;
- char *w, *raww, *tail;
- int brack = 0;
- int more;
- char longname[512];
-
- if(p == NULL || (f = PoolInputFile(p)) == NULL)
- return 0;
-
- /* Skip a semicolon if it's the first thing we see -- 'stuff' compatibility.
- */
- if(fnextc(f, 0) == ';')
- fgetc(f);
-
- do {
- more = 0;
- switch(c = fnextc(f, 0)) {
- case '<':
- case ':':
- case '@':
- fgetc(f);
- w = fdelimtok("{}()", f, 0);
- /*
- * Consider doing a path search.
- * Do this before calling HandleReferringTo()
- * to prevent spurious error messages.
- */
- if(c == '<' && (h = HandleByName(w, &GeomOps)) == NULL && w[0] != '/') {
- w = findfile(PoolName(p), raww = w);
- if(w == NULL) {
- OOGLSyntax(PoolInputFile(p),
- "Error reading \"%s\": can't find file \"%s\"",
- PoolName(p), raww);
- }
- }
- h = HandleReferringTo(c, w, &GeomOps, NULL);
- if(h != NULL) {
- g = (Geom *)HandleObject(h);
- RefIncr((Ref*)g);
- }
- break;
-
- case '{':
- brack++;
- fgetc(f);
- break;
- case '}':
- if(brack--) { fgetc(f); braces = 1; }
- break;
-
- case 'g':
- if(fexpectstr(f, "geom"))
- return 0;
- more = 1;
- break;
-
- case 'd':
- if(fexpectstr(f, "define"))
- return 0;
- more = 1;
- hname = HandleCreate( ftoken(PoolInputFile(p), 0), &GeomOps );
- break;
-
- case 'a':
- if(fexpectstr(f, "appearance"))
- return 0;
- ap = ApFLoad(NULL, PoolInputFile(p), PoolName(p));
- more = 1;
- break;
-
- case '=':
- fgetc(f); /* Skip '=' and fall into... */
-
- default:
- /*
- * Load literal object.
- * First try to guess object type from its file name.
- */
- empty = 0;
- (void) fnextc(f, 0); /* [Prime stdio buffer] */
- mark = stdio_setmark( NULL, PoolInputFile(p) );
-
- Class = GeomFName2Class( PoolName(p) );
-
- g = NULL;
- first = 1;
- tgp = gp ? gp : &g;
- thp = hp ? hp : &h;
-
- if(Class) {
- if(Class->import)
- g = (*Class->import)(p);
- else if(Class->fload)
- g = (*Class->fload)(PoolInputFile(p), PoolName(p));
- first = 0;
- if(g)
- break;
- }
-
- /*
- * If not, try all known classes.
- */
- GeomKnownClassInit(); /* Ensure all classes entered */
-
- it = GeomClassIterate();
- while (g == NULL && (Class = GeomNextClass(&it)) != NULL) {
- if(Class->import == NULL && Class->fload == NULL)
- continue;
- /*
- * Try to seek back to our initial position.
- */
- if(!first && !stdio_seekmark(mark)) {
- /* No luck. Might as well give up right now. */
- OOGLSyntax(PoolInputFile(p),
- "Error reading \"%s\": can't seek back far enough (on pipe?)",
- PoolName(p));
- break;
- }
-
- if(Class->import)
- g = (*Class->import)(p);
- else if(Class->fload)
- g = (*Class->fload)(PoolInputFile(p), PoolName(p));
- first = 0;
- }
- if(g == NULL) {
- OOGLFree(mark);
- return 0;
- }
- }
- } while(brack > 0 || more);
-
-
- if(hname != NULL) {
- if(g)
- HandleSetObject(hname, (Ref *)g);
- h = hname;
- }
-
- /*
- * Leave results where we're told to
- */
- if(h != NULL && hp != NULL && *hp != h) {
- if(*hp)
- HandlePDelete(hp);
- *hp = h;
- }
- if(ap != NULL || aphandle != NULL) {
- if(g == NULL)
- g = GeomCreate("inst", CR_END);
- if(g->ap)
- ApDelete(g->ap);
- if(g->aphandle)
- HandlePDelete(&g->aphandle);
- g->ap = ap;
- g->aphandle = aphandle;
- }
- if(g != NULL && gp != NULL && *gp != g) {
- if(*gp != NULL)
- GeomDelete(*gp);
- *gp = g;
- } else if(g) /* Maintain ref count */
- GeomDelete(g);
-
- if(mark != NULL)
- OOGLFree(mark);
- return (g != NULL || h != NULL || (empty && braces));
- }
-
-
- int
- GeomStreamOut(Pool *p, Handle *h, Geom *g)
- {
- int putdata;
- int brack;
-
- if(PoolOutputFile(p) == NULL)
- return 0;
-
- if(g == NULL && h != NULL && h->object != NULL)
- g = (Geom *)h->object;
-
- if(g == NULL && h == NULL) {
- fprintf(PoolOutputFile(p), "{ }\n");
- return 1;
- }
-
- brack = (p->level > 0 || (g && (g->ap || g->aphandle)) || h != NULL);
-
- if(brack)
- fprintf(PoolOutputFile(p), "{ ");
-
- if(p->otype & 4) fprintf(PoolOutputFile(p), "# %d refs\n", g->ref_count); /* debug */
-
- if(g && (g->ap || g->aphandle))
- ApFSave(g->ap, g->aphandle, PoolOutputFile(p), PoolName(p));
-
- putdata = PoolStreamOutHandle( p, h, g != NULL );
- if(g != NULL && putdata) {
- if(brack)
- fprintf(PoolOutputFile(p), "= ");
- PoolIncLevel(p, 1);
- if(g->Class->export)
- (*g->Class->export)(g, p);
- else if(g->Class->fsave)
- (*g->Class->fsave)(g, PoolOutputFile(p), PoolName(p));
- PoolIncLevel(p, -1);
- }
- if(brack)
- fprintf(PoolOutputFile(p), "}\n");
- return !ferror(PoolOutputFile(p));
- }
-